home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 2 / United Public Domain Gold 2.iso / education / pe023.dms / pe023.adf / ALGORHYTHMS / SOURCE / ALGORHYTHMS.C next >
C/C++ Source or Header  |  1988-10-05  |  21KB  |  741 lines

  1. /*AlgoRhythms.c*/
  2. /*Thomas E. Janzen 4 September 1989; 2-11-90 */
  3. /*18 September 1989 26 nov 89 11 December 1989 16 December 1989*/
  4. /*Music played with this program Copyright 1990 Thomas E. Janzen */
  5. /*This program Copyright 1990 Thomas E. Janzen All Rights Reserved */
  6. /*This program is for a Commodore (TM) Amiga (TM) 500 playing MIDI */
  7. /*Lattice C 5.05*/
  8. /*out the serial port to a single MIDI channel with MAXVOICE voices */
  9. /*The music is randomized by changes slowly by sinusoidal functions */
  10. /*
  11. **  FACILITY:
  12. **
  13. **    AlgoRhythms music improviser on Commodore (TM) Amiga (TM)
  14. **    compiled with Lattice (TM) C 5.05
  15. **
  16. **  ABSTRACT:
  17. **
  18. **    Algorhythms improvises music over the MIDI serial port.
  19. **    See the manual.
  20. **
  21. **  AUTHOR: Thomas E. Janzen
  22. **
  23. **  CREATION DATE:    26-MAR-1990
  24. **
  25. **  MODIFICATION HISTORY:
  26. **    DATE    NAME    DESCRIPTION
  27. **--
  28. */
  29.  
  30. #define    TWOPI    (2 * PI)
  31. #define    DURMAX    2.0
  32. #define PROJECT (0)
  33. #define FORM (1)
  34. #define SCALE (2)
  35. #define CHANNEL (3)
  36. #include    "limits.h"
  37. #include    "math.h"
  38. #include    "stdlib.h"
  39. #include    "stdio.h"
  40. #include    "string.h"
  41. #include    "intuition/intuition.h"
  42. #include    "exec/memory.h"
  43. #include    "exec/interrupts.h"
  44. #include    "exec/devices.h"
  45. #include    "devices/serial.h"
  46. #include <proto/dos.h>
  47. #include <proto/graphics.h>
  48. #include <proto/exec.h>
  49. #include <proto/mathffp.h>
  50. #include <proto/intuition.h>
  51. #include    "Workbench/startup.h"
  52.  
  53. #define    STRINGSIZE 80
  54.  
  55. #include "musictimer.h"
  56. #include "window.h"
  57.  
  58. extern struct Window *w;
  59.  
  60. #include "musicserial.h"
  61. #include "Gadgets.h"
  62.  
  63. struct Parameter Randomize_Parameter(void);
  64.  
  65. #include "files.h"
  66. #include "DrawForm.h"
  67.  
  68. extern struct GfxBase *GfxBase;
  69. extern struct IntuitionBase *IntuitionBase;
  70. extern struct DOSBase *DOSBase;
  71. extern struct MathBase *MathBase;
  72.  
  73. void MakeEvent(struct NoteEvent *, struct Character *, 
  74.     const double CurTime); /* Calculates the next note to send out */
  75.  
  76. struct Parameter {
  77.     double CenterCycle;
  78.     double CenterPhase;
  79.     double SpreadCycle;
  80.     double SpreadPhase;
  81. };
  82.  
  83. int fubar=FALSE;
  84.  
  85. static struct Parameter Pitch_Form     = {180.0,-PID2,200.0,-PID2};
  86. static struct Parameter Thickness_Form    = {0.0,    0.0,190.0,-PID2};
  87. static struct Parameter Dynamics_Form    = {170.0,-PID2,165  ,-PID2};
  88. static struct Parameter Duration_Form    = {200.0, PID2,180.0, PID2};
  89.  
  90. struct Character {
  91.     double    PitchSpread;    /*range of pitches*/
  92.     double    PitchCenter;    /* ~ median pitch*/
  93.     double    DynamicSpread;    /*range of dynamic levels*/
  94.     double    DynamicCenter;    /* ~ median of dynamic levels*/
  95.     double    DurSpread;    /*range of durations */
  96.     double    DurCenter;    /* ~ median of durations */
  97.     double    Thickness;     /*number of voices playing at once*/
  98. };
  99.  
  100. struct Character *ranges(
  101.     struct Parameter *Pitch, 
  102.     struct Parameter *Dyn, 
  103.     struct Parameter *Dur,  
  104.     struct Parameter *Thickness, 
  105.     const double phase);
  106.  
  107. int EventPointer = 0;
  108.  
  109. /*Pitch Range*/
  110. int    range=10;
  111. int    halfrange=5;
  112.  
  113. #include "scales.h"
  114. #include "menus.h"
  115.  
  116. int ParseMessage(int class, int code, double *StrTime,
  117.     struct Parameter *PitchForm, struct Parameter *RhythmForm,
  118.     struct Parameter *DynamicsForm, struct Parameter *TextureForm,
  119.     double *Duration,int *tempo, struct NoteEvent *Events);
  120.  
  121. int    scale[120] = {48,50,53,55,58,60,62,65,67,70,72,74,77};
  122.     /* holds the scale of notes allowed */
  123.  
  124. static    int    numvoices=MAXVOICE;
  125.  
  126. static struct timeval timval;
  127.  
  128. int playing = FALSE; /* playing music */
  129. int started= FALSE;
  130. int done=FALSE;
  131.  
  132. int quit=FALSE;
  133. int DelayTicks = 2;
  134.  
  135. double MaxNoteLen = 2.0;
  136. double MinNoteLen = 0.0;
  137. double NoteLenDif = 2.0;
  138.  
  139. void main(void)
  140. {
  141.     register int tick=0;
  142.     int code, class; /* mouse codes esp. for menus */
  143.     int Action=0;
  144.     register double    CurTime; /*the current time in seconds*/
  145.     double    PieceDuration=600.0; /*piece length in seconds*/
  146.     int tempo;
  147.     static struct NoteEvent Events[MAXVOICE];
  148.     register int temptv_secs;
  149.     register int temptv_micro;
  150.     static struct Character Now;
  151.     int    i;
  152.     static double StartTime=0.0;/*time that the program starts to execute*/
  153.  
  154.     register double phase;
  155.  
  156.     MakeWindow();
  157.     Open_MIDI_Port();
  158.     if(fubar == TRUE) goto cleanup2;
  159.     Init_Menu(); /*menu*/
  160.  
  161.     tempo=50/DelayTicks;
  162.  
  163.     range=InstallScale(11,scale);
  164.     halfrange=range/2;
  165.  
  166.     for (i=0;i<MAXVOICE;i++) {
  167.         Events[i].Pitch=halfrange;
  168.         Events[i].Dynamic=0.0;
  169.         Events[i].StartTime=0.0;
  170.         Events[i].Duration=0.0;
  171.         Events[i].Channel=0;
  172.         Events[i].CurPitch=60;
  173.         Events[i].LowPitch=24;
  174.         Events[i].HighPitch=108;
  175.         Events[i].Walking=FALSE;
  176.     }
  177.  
  178.     /*set the form of the piece*/
  179.     StartTimer();
  180.     GetSysTime(&timval);
  181.     temptv_secs = (int)timval.tv_secs;
  182.     temptv_micro= (int)timval.tv_micro;
  183.     srand(temptv_micro);
  184.     StartTime=(double)temptv_secs+(((double)temptv_micro)*0.000001);
  185.         /*Save Time the program started*/
  186.     CurTime=0.0;
  187.  
  188.     GetSysTime(&timval);
  189.     StartTime=
  190.      (double)timval.tv_secs+(((double)timval.tv_micro)*0.000001);
  191.         /*Save Time the program started*/
  192.     phase=TWOPI*CurTime;
  193.  
  194.     Pitch_Form=Randomize_Parameter();
  195.     Duration_Form=Randomize_Parameter();
  196.     Dynamics_Form=Randomize_Parameter();
  197.     Thickness_Form=Randomize_Parameter();
  198.  
  199.     DrawForm(PieceDuration,&Pitch_Form,&Duration_Form,
  200.         &Dynamics_Form,&Thickness_Form);
  201.  
  202.     Now = *ranges(&Pitch_Form,&Dynamics_Form,
  203.         &Duration_Form,&Thickness_Form, phase);
  204.         /*Initialize the ranges (pitch, dynamic, duration)*/
  205.  
  206.     /*Master Control Loop*/
  207.     while(!(quit)) {
  208.         GetSysTime(&timval);
  209.         CurTime=(double)timval.tv_secs +
  210.             (((double)timval.tv_micro)*0.000001)-StartTime;
  211.         while (playing = (!(done) && started) && !(quit)) {
  212.             GetSysTime(&timval);
  213.             CurTime=(double)timval.tv_secs +
  214.             (((double)timval.tv_micro)*0.000001)-StartTime;
  215.             phase = TWOPI * CurTime;
  216.             Now = *ranges(&Pitch_Form,&Dynamics_Form,
  217.             &Duration_Form,&Thickness_Form, phase);
  218.             for (EventPointer=0;EventPointer < numvoices;
  219.                  EventPointer++) {
  220.                 if((CurTime-Events[EventPointer].StartTime)
  221.                     > Events[EventPointer].Duration) {
  222.                     MakeEvent(&Events[EventPointer],
  223.                     &Now, CurTime);
  224.                 }
  225.             }
  226.             DrawTime(CurTime,PieceDuration);
  227.             if (Action=CheckMenu(&class, &code)) {
  228.                 ParseMessage(class,code,&StartTime,
  229.                 &Pitch_Form,&Duration_Form,&Dynamics_Form,
  230.                 &Thickness_Form,&PieceDuration,&tempo,
  231.                 Events);
  232.             }
  233.             if (DelayTicks) {
  234.                 for(tick=0;tick<DelayTicks;tick=tick+2) {
  235.                     SendFunction(CLOCKFUNCT);
  236.                     Delay(2);/*give music a pulse*/
  237.                 }
  238.             }
  239.             if(done=(CurTime > PieceDuration)) {
  240.                 StopAllNotes(Events);
  241.                 started=FALSE;
  242.             }
  243.         }
  244.         Wait(1 << w->UserPort->mp_SigBit);
  245.         if (Action=CheckMenu(&class, &code)) {
  246.             ParseMessage(class,code,&StartTime,
  247.             &Pitch_Form,&Duration_Form,&Dynamics_Form,
  248.             &Thickness_Form,&PieceDuration,&tempo,Events);
  249.             }
  250.         continue;
  251.     }    
  252. cleanup1:
  253.     CloseMenu();
  254.     StopAllNotes(Events);
  255.     Delay(10);
  256.     RemoveTimer();
  257. cleanup2: /* exit here if the serial port wouldn't open*/
  258.     ShutWindow();
  259.     StopMIDI();
  260.     exit(0);
  261. } /* end main*/
  262.  
  263. struct Character *ranges(
  264.     struct Parameter *Pitch, 
  265.     struct Parameter *Dyn,
  266.     struct Parameter *Dur,  
  267.     struct Parameter *Thickness, 
  268.     const double phase)
  269. {
  270.     static struct Character NextNow;
  271.     register double realhalfrange;
  272.  
  273.     realhalfrange=(double)halfrange;
  274.  
  275.     NextNow.PitchSpread=(sin((phase/Pitch->SpreadCycle)+
  276.         Pitch->SpreadPhase)+1.0)*
  277.         realhalfrange;
  278.         /*Pitch range is a sin function of time*/
  279.     NextNow.PitchCenter=(sin((phase/(Pitch->CenterCycle))+
  280.         (Pitch->CenterPhase))+1.0)*
  281.         realhalfrange; 
  282.         /*Median Pitch is a sin funct of time*/
  283.  
  284.     if((NextNow.PitchCenter - (NextNow.PitchSpread/2)) < 0) {
  285.         NextNow.PitchCenter = 1.0 + ((NextNow.PitchCenter+
  286.             (NextNow.PitchSpread/2))/2);
  287.     }
  288.     else {
  289.         if((NextNow.PitchCenter+(NextNow.PitchSpread/2)) > 
  290.             (double)range) {
  291.             NextNow.PitchCenter = realhalfrange - 1.0  + 
  292.             ((NextNow.PitchCenter - (NextNow.PitchSpread/2.0))
  293.             /2.0);
  294.         }
  295.     }
  296.  
  297.     NextNow.DynamicSpread=(sin((phase/(Dyn->SpreadCycle))+
  298.         Dyn->SpreadPhase)+1.01)*63;
  299.         /*Range of dynamics is a sin function of time*/
  300.     NextNow.DynamicCenter=((sin((phase/(Dyn->CenterCycle))+
  301.         Dyn->CenterPhase)+1.01)* 50) + 25;
  302.         /*Median dynamic is a sin function of time*/
  303.     NextNow.DurSpread=(sin((phase/(Dur->SpreadCycle))+
  304.         Dur->SpreadPhase)+1.01)*NoteLenDif;
  305.         /* Range of durations is a sin function of time*/
  306.     NextNow.DurCenter=((sin((phase/(Dur->CenterCycle))+
  307.         Dur->CenterPhase)+1.01)*NoteLenDif)+MinNoteLen; 
  308.         /*Median duration is a sin function of time*/
  309.     NextNow.Thickness=((sin((phase/(Thickness->SpreadCycle))+
  310.         Thickness->SpreadPhase)+1.01)*(double)numvoices/2.0)-1.0;
  311.         /*the number of voices playing is a sin function of time*/
  312.     return &NextNow;
  313. }
  314.  
  315. struct Parameter Randomize_Parameter(void)
  316. {
  317.     struct Parameter Temp;
  318.     register double reallong_max;
  319.     
  320.     reallong_max=(double)LONG_MAX;
  321.     Temp.CenterCycle=((double)rand()/reallong_max)*(120)+90;
  322.         /*1.5 to 3.5 minutes */
  323.     Temp.CenterPhase=((double)rand()/reallong_max)*TWOPI;
  324.     Temp.SpreadCycle=((double)rand()/reallong_max)*(120)+90;
  325.         /*1.5 to 3.5 minutes */
  326.     Temp.SpreadPhase=((double)rand()/reallong_max)*TWOPI;
  327.     return Temp;
  328. }
  329.  
  330. void MakeEvent(struct NoteEvent *NewEvent,
  331.     struct Character *Style, const double CurTime) {
  332.     int LowNote;
  333.     int HighNote;
  334.     int OKRandNote;
  335.     
  336.     int    walk;
  337.     register double reallong_max;    
  338.     register double reallong_maxdiv2;
  339.     double    NewDynamic; /*a temporary holder of a new dynamic value*/
  340.     double    NewDuration; /*a temporary holder of a new duration value*/
  341.     int    NewPitchIndex;
  342.  
  343.     OKRandNote=TRUE;
  344.     reallong_max=(double)LONG_MAX;
  345.     reallong_maxdiv2=reallong_max/2.0;
  346.     PlayNoteOff(NewEvent);
  347.         /*Turn off the previous note*/
  348.         /*for this voice*/
  349.     if (EventPointer<=(int)(Style->Thickness)) {
  350.         
  351.         NewDynamic= ((((double)rand()/reallong_maxdiv2))-1.0)
  352.             *(Style->DynamicSpread)+(Style->DynamicCenter);
  353.             /*get random dynamic*/
  354.         if (NewDynamic > 127){ /*compress dynamic to be valid*/
  355.             NewDynamic=127;
  356.             }
  357.         if (NewDynamic < 0 ) { /*compress dynamic to be valid*/
  358.             NewDynamic=0;
  359.         }
  360.         NewEvent->Dynamic=(int)NewDynamic;/* make dynamic a byte*/
  361.  
  362.         NewDuration=((((double)rand()/reallong_maxdiv2))-1.0)
  363.             * (Style->DurSpread)+(Style->DurCenter) +
  364.             ((Style->DurSpread)/8);
  365.             /*Get random duration*/
  366.         if (NewDuration<0.0) { /*force duration positive*/
  367.             NewDuration = 0;
  368.         }
  369.         NewEvent->Duration=NewDuration; /*Put duration in */
  370.         /* durations list */
  371.         NewEvent->StartTime=CurTime;
  372.         /*Make attacktime for this note */
  373.         /* equal to current time */
  374.  
  375.         /*PITCH*/
  376.         if(NewEvent->Walking) {
  377.             HighNote=
  378.             ((NewEvent->CurPitch) >= NewEvent->HighPitch);
  379.             LowNote=
  380.             ((NewEvent->CurPitch) <= NewEvent->LowPitch);
  381.             walk = (rand() % 3)-1;
  382.             if(LowNote) {
  383.                 walk=1;
  384.             }
  385.             if(HighNote) {
  386.                 walk=-1;
  387.             }
  388.             NewPitchIndex=(NewEvent->Pitch)+walk;
  389.         }
  390.         else {
  391.             NewPitchIndex= 
  392.             ((((double)rand()/reallong_maxdiv2))-1.0)
  393.             * (Style->PitchSpread)+(Style->PitchCenter);
  394.             HighNote=
  395.             ((scale[NewPitchIndex]) >= NewEvent->HighPitch);
  396.             LowNote=
  397.             ((scale[NewPitchIndex]) <= NewEvent->LowPitch);
  398.             OKRandNote=(!(HighNote) && (!(LowNote)));
  399.         }
  400.         if (NewPitchIndex >= range) {
  401.             NewPitchIndex=range-1; 
  402.             /*fold under if too hi*/
  403.             }
  404.         if (NewPitchIndex < 0) {    
  405.             /*fold up if too low */
  406.             NewPitchIndex = 0;
  407.             }
  408.         NewEvent->Pitch=(int)NewPitchIndex; /*pitch in note list*/
  409.         NewEvent->CurPitch=scale[(int)NewPitchIndex];
  410.         /*Play the note*/
  411.         if (playing && OKRandNote)PlayNoteOn(NewEvent);
  412.     }
  413. }
  414.  
  415. int ParseMessage(int class, int code, double *StrTime,
  416.     struct Parameter *PitchForm, struct Parameter *RhythmForm,
  417.     struct Parameter *DynamicsForm, struct Parameter *TextureForm,
  418.     double *Duration,int *tempo, struct NoteEvent Events[MAXVOICE]
  419.     ) {
  420.     int i;
  421.     int tempint;
  422.     int Status; /* file status */
  423.     extern int midi_addr;
  424.     int item=0; int subitem=0;
  425.     static double StopTime, ContTime;
  426.     static char AnswerBuf[96];
  427.     static char FileString[64]={0,0,0,0,0,0,0,0,0};
  428.     char *AnsBuf;
  429.     static char FileNameString[] = "File Name";
  430.     static char DurationString[]="Duration in Seconds";
  431.     static char PaceString[]="Rhythmic Pace";
  432.     static char DynamicString[]="Dynamics";
  433.     static char TextureString[]="Texture";
  434.     static char PitchString[]="Pitch";
  435.     
  436.     static char DynamicMean[]="Dynamic Mean";
  437.     static char DynamicSpread[]="Dynamic Spread";
  438.     static char TextureSpread[]="Texture Spread";
  439.     static char PitchMean[]="Pitch Mean";
  440.     static char PitchSpread[]="Pitch Spread";
  441.     static char RhythmMean[]="Rhythm Mean";
  442.     static char RhythmSpread[]="Rhythm Spread";
  443.     
  444.     static char VoiceString[]="Number of Voices";
  445.     static char BlankString[4]=" ";
  446.     static char SpreadPeriodString[]="Spread Period";
  447.     static char MeanPeriodString[]="Mean Period";
  448.     static char PulseString[]="Pulses per Second";
  449.     static char TransposeString[]="Tranpose";
  450.     static char LoadFileString[]="Load File";
  451.     static char SaveFileString[]="Save File";
  452.     static char NoteLenString[]="Note Length";
  453.     static char MinimumString[]="Minimum";
  454.     static char MaximumString[]="Maximum";
  455.     
  456.     static char About1String[24]=
  457.         "Welcome to AlgoRhythms";
  458.     static struct IntuiText About1Txt=
  459.         {2,1,JAM1,5,4,NULL,About1String,NULL};
  460.     static char About2String[32]=
  461.         "Copyright 1990 Thomas E. Janzen";
  462.     static struct IntuiText About2Txt=
  463.         {2,1,JAM1,5,15,NULL,About2String,&About1Txt};
  464.     static char ThanksString[]="Thanks";
  465.     struct IntuiText ThanksTxt={2,1,JAM1,5,4,NULL,ThanksString,
  466.         NULL};
  467.     
  468.     int Response;
  469.     switch(class) {
  470.      case NEWSIZE:
  471.             DrawForm(*Duration,PitchForm,RhythmForm,
  472.             DynamicsForm,TextureForm);
  473.         break;
  474.      case MENUPICK:
  475.       if (code != MENUNULL) {
  476.        item=ITEMNUM(code);
  477.        subitem=SUBNUM(code);
  478.        switch(MENUNUM(code)) {
  479.         case PROJECT:
  480.          if (item != NOITEM) switch(item) {
  481.           case 0: /*quit*/
  482.            quit=TRUE;
  483.            break;
  484.           case 1: /*About*/
  485.            Response=AutoRequest(w,&About2Txt,&ThanksTxt,&ThanksTxt,
  486.            0L,0L,300L,60L);
  487.            break;
  488.           case 2: /*save*/
  489.            sprintf(AnswerBuf,"%s",FileString);
  490.            Status=GetStringInput(AnswerBuf,SaveFileString,
  491.                    FileNameString);
  492.         if (Status == 1) break;
  493.         Status=Save_File(AnswerBuf,Duration,&range,scale,
  494.         &numvoices,tempo,PitchForm,TextureForm,DynamicsForm,
  495.         RhythmForm,Events,MinNoteLen,MaxNoteLen);
  496.         if (Status == 0) {
  497.             __builtin_strcpy(FileString,AnswerBuf);
  498.         }
  499.         else {
  500.             DisplayBeep(NULL);
  501.         }
  502.            break;
  503.           case 3: /*load*/
  504.            sprintf(AnswerBuf,"%s",FileString);
  505.            Status=GetStringInput(AnswerBuf,LoadFileString,
  506.                    FileNameString);
  507.         if (Status == 1) break;
  508.         Status=Read_File(AnswerBuf,Duration,
  509.         &range,scale,&numvoices,tempo,PitchForm,
  510.         TextureForm,DynamicsForm,RhythmForm,Events,
  511.         &MinNoteLen,&MaxNoteLen);
  512.         if (Status == 0) {
  513.             if (*tempo == 0) {
  514.                 DelayTicks=0;
  515.             }
  516.             else {
  517.                 DelayTicks=50/(*tempo);
  518.             }
  519.             halfrange=range/2;
  520.             __builtin_strcpy(FileString,AnswerBuf);
  521.             DrawForm(*Duration,PitchForm,RhythmForm,
  522.             DynamicsForm,TextureForm);
  523.         }
  524.         else {
  525.             DisplayBeep(NULL);
  526.         }
  527.            break;
  528.           case 4: /* Continue */
  529.               started=TRUE;
  530.             GetSysTime(&timval);
  531.             ContTime=(double)timval.tv_secs+
  532.         (((double)timval.tv_micro)*0.000001);
  533.         *StrTime=*StrTime+(ContTime-StopTime);
  534.           break;
  535.           case 5: /*stop*/
  536.            started=FALSE;
  537.            for (i=0;i<MAXVOICE;i++) {
  538.         (&Events[i])->StartTime=0.0;
  539.         (&Events[i])->Duration=0.0;
  540.            }
  541.         StopAllNotes(Events);
  542.            GetSysTime(&timval);
  543.            StopTime=(double)timval.tv_secs+
  544.         (((double)timval.tv_micro)*0.000001);
  545.            break;
  546.           case 6: /*Start to Play*/
  547.            started=TRUE;
  548.            done=FALSE;
  549.            GetSysTime(&timval);
  550.            *StrTime=(double)timval.tv_secs+
  551.         (((double)timval.tv_micro)*0.000001);
  552.            for (i=0;i<MAXVOICE;i++) {
  553.         (&Events[i])->StartTime=0.0;
  554.         (&Events[i])->Duration=0.0;
  555.            }
  556.            SendFunction(STARTFUNCT);
  557.            break;
  558.           } /*switch itemnum*/
  559.           break;
  560.           case FORM:
  561.            if (item != NOITEM) switch(item) {
  562.         case 0: /*note length*/
  563.          if (subitem != NOSUB) switch(subitem) {
  564.            case 0: /*minimum*/
  565.             sprintf(AnswerBuf,"%5.2f",MinNoteLen);
  566.                 AnsBuf=GetGadgetInput(AnswerBuf,
  567.                NoteLenString,MinimumString);
  568.             MinNoteLen=atof(AnsBuf);
  569.             NoteLenDif=MaxNoteLen-MinNoteLen;
  570.            break;
  571.            case 1: /*maximum*/
  572.             sprintf(AnswerBuf,"%5.2f",MaxNoteLen);
  573.                 AnsBuf=GetGadgetInput(AnswerBuf,
  574.                NoteLenString,MaximumString);
  575.             MaxNoteLen=atof(AnsBuf);
  576.             NoteLenDif=MaxNoteLen-MinNoteLen;
  577.            break;
  578.         }
  579.         break;
  580.             case 1: /*Texture*/
  581.          if (subitem != NOSUB) switch(subitem) {
  582.         case 0: /* Randomize */
  583.            *TextureForm=Randomize_Parameter();
  584.         break;
  585.           case 1: /*Spread Period*/
  586.            sprintf(AnswerBuf,"%2.0f",(TextureForm->SpreadCycle));
  587.                AnsBuf=GetGadgetInput(AnswerBuf,
  588.                TextureString,SpreadPeriodString);
  589.            TextureForm->SpreadCycle=atof(AnsBuf);
  590.            break;
  591.           case 2: /*Spread Phase*/
  592.            TextureForm->SpreadPhase=
  593.            GetPhaseInput(TextureForm->SpreadPhase,TextureSpread);
  594.            break;
  595.         }
  596.         break;
  597.           case 2: /*Dynamic*/
  598.          if (subitem != NOSUB) switch(subitem) {
  599.         case 0: /* Randomize */
  600.            *DynamicsForm=Randomize_Parameter();
  601.         break;
  602.           case 1: /* Spread Phase*/
  603.            DynamicsForm->SpreadPhase=
  604.            GetPhaseInput(DynamicsForm->SpreadPhase,DynamicSpread);
  605.            break;
  606.           case 2: /* Spread Period*/
  607.            sprintf(AnswerBuf,"%2.0f",DynamicsForm->SpreadCycle);
  608.                AnsBuf=GetGadgetInput(AnswerBuf,
  609.                DynamicString,SpreadPeriodString);
  610.            DynamicsForm->SpreadCycle=atof(AnsBuf);
  611.            break;
  612.           case 3: /* mean Phase*/
  613.            DynamicsForm->CenterPhase=
  614.            GetPhaseInput(DynamicsForm->CenterPhase,DynamicMean);
  615.            break;
  616.           case 4: /* Mean Period*/
  617.            sprintf(AnswerBuf,"%2.0f",DynamicsForm->CenterCycle);
  618.            AnsBuf=GetGadgetInput(AnswerBuf,
  619.                DynamicString,MeanPeriodString);
  620.            DynamicsForm->CenterCycle=atof(AnsBuf);
  621.            break;
  622.         }
  623.         break;
  624.           case 3: /*Rhythm*/
  625.            if (subitem != NOSUB) switch(subitem) {
  626.         case 0: /* Randomize */
  627.            *RhythmForm=Randomize_Parameter();
  628.         break;
  629.         case 1: /* Spread Phase*/
  630.            RhythmForm->SpreadPhase=
  631.            GetPhaseInput(RhythmForm->SpreadPhase,RhythmSpread);
  632.         break;
  633.         case 2: /* Spread Period*/
  634.          sprintf(AnswerBuf,"%2.0f",RhythmForm->SpreadCycle);
  635.              AnsBuf=GetGadgetInput(AnswerBuf,
  636.              PaceString,SpreadPeriodString);
  637.          RhythmForm->SpreadCycle=atof(AnsBuf);
  638.         break;
  639.         case 3: /* mean Phase*/
  640.            RhythmForm->CenterPhase=
  641.                GetPhaseInput(RhythmForm->CenterPhase,RhythmMean);
  642.         break;
  643.         case 4: /* Mean Period*/
  644.          sprintf(AnswerBuf,"%2.0f",RhythmForm->CenterCycle);
  645.              AnsBuf=GetGadgetInput(AnswerBuf,
  646.              PaceString,MeanPeriodString);
  647.          RhythmForm->CenterCycle=atof(AnsBuf); 
  648.         break;
  649.            }
  650.         break;
  651.           case 4: /*Pitch*/
  652.          if (subitem != NOSUB) switch(subitem) {
  653.         case 0: /* Randomize */
  654.            *PitchForm=Randomize_Parameter();
  655.         break;
  656.           case 1: /* Spread Phase*/
  657.            PitchForm->SpreadPhase=
  658.                GetPhaseInput(PitchForm->SpreadPhase,
  659.                 PitchSpread);
  660.            break;
  661.           case 2: /* Spread Period*/
  662.            sprintf(AnswerBuf,"%2.0f",PitchForm->SpreadCycle);
  663.                AnsBuf=GetGadgetInput(AnswerBuf,
  664.                PitchString,SpreadPeriodString);
  665.            PitchForm->SpreadCycle=atof(AnsBuf);
  666.            break;
  667.           case 3: /* mean Phase*/
  668.            PitchForm->CenterPhase=
  669.                GetPhaseInput(PitchForm->CenterPhase,PitchMean);
  670.            break;
  671.           case 4: /* Mean Period*/
  672.            sprintf(AnswerBuf,"%2.0f",PitchForm->CenterCycle);
  673.            AnsBuf=GetGadgetInput(AnswerBuf,
  674.                PitchString,MeanPeriodString);
  675.            PitchForm->CenterCycle=atof(AnsBuf); 
  676.            break;
  677.         }
  678.         break;
  679.            case 5: /*Duration*/
  680.         sprintf(AnswerBuf,"%2.0f",*Duration);
  681.             AnsBuf=GetGadgetInput(AnswerBuf,
  682.             BlankString,DurationString);
  683.         *Duration=atof(AnsBuf);
  684.         break;
  685.            case 6: /*pulse*/
  686.         sprintf(AnswerBuf,"%d",*tempo);
  687.         AnsBuf=GetGadgetInput(AnswerBuf,
  688.             BlankString,PulseString);
  689.         *tempo=abs(atoi(AnsBuf));
  690.         if (*tempo == 0) {
  691.             DelayTicks=0;
  692.         }
  693.         else {
  694.             DelayTicks=50/(*tempo);
  695.         }
  696.         break;
  697.            case 7: /*ReDraw*/
  698.             DrawForm(*Duration,PitchForm,RhythmForm,
  699.             DynamicsForm,TextureForm);
  700.            break;
  701.            case 8: /*numvoices*/
  702.         sprintf(AnswerBuf,"%d",numvoices);
  703.         AnsBuf=GetGadgetInput(AnswerBuf,
  704.             BlankString,VoiceString);
  705.         tempint=atoi(AnsBuf);
  706.         if((tempint <= MAXVOICE)&&(tempint > 0)) {
  707.             numvoices=tempint;
  708.         }
  709.         else {
  710.             DisplayBeep(NULL);
  711.         }
  712.         break;
  713.           } /*switch itemnum*/
  714.           break;
  715.           case SCALE:
  716.            if (item != NOITEM) switch(item) {
  717.             case 0: /*transpose*/
  718.          sprintf(AnswerBuf,"0");
  719.          AnsBuf=GetGadgetInput(AnswerBuf,
  720.              BlankString,TransposeString);
  721.          TransposeScale(atoi(AnsBuf),scale,range);
  722.         break;
  723.                 default:
  724.              range=InstallScale(12-item,scale);
  725.              halfrange=range/2;
  726.            } /*switch itemnum*/
  727.           break;
  728.           case CHANNEL:
  729.         GetChannelStuff(&Events[item],item);
  730.         break;
  731.           } /*switch menunum*/
  732.          } /*while menunull*/
  733.          break;
  734.          case CLOSEWINDOW:
  735.         quit=TRUE;
  736.          break;
  737.         } /*switch class*/
  738.     return (0);
  739. } /*end function*/
  740.  
  741.